<?php
/*! \brief
 * This is WFWidgetPoolDB class
 * Manipulate all the db handle of WidgetPool
 * \author William Su
 */
require_once (dirname(__FILE__) . '/../../db/DB.abstract.php');
class WFWidgetPoolDB extends ADB
{
    /*private $objWidgetPoolFactory;
    private $objWidgetPoolManager;
    private $objFramework;*/
    /**
     * @var WFConfig
     */
    private $objConfig;
    ////private $objDataObject;
    public function __construct($objFramework){
        parent::__construct($objFramework);
        $this->objWidgetPoolManager = $this->objWidgetPoolFactory->getWidgetPoolManager();
        $this->objConfig = $this->objFramework->getConfigFactory()->getConfig();
    }
    /**
     *\brief Description
     * - setter of $objConfig (WFConfug)
     */
    public function setObjConfig($objConfig){
        $this->objConfig = $objConfig;
    }
    /**
     *\brief Description
     * - setter of $objDataObject (WFDataObject)
     */
    public function setObjDataObject($objDataObject){
        $this->objDataObject = $objDataObject;
    }
    /**
     *\brief Description
     * - This method will initial create relative table of WidgetPool
     * - If success return true, If failed will raised Exception
     *\par Variable
     * - EX : $mixTableName string
     * WP_UPDATE_LOG
     * - EX : $mixTableName array
     * array (
     * 0 => 'WIDGET',
     * 1 => 'WIDGET_CATEGORY'
     * )
     */
    public function initWidgetPoolDBSchema($mixTableName = null){
        $defaultArrTable = $this->objWidgetPoolFactory->getWidgetPoolOpt()->getWidgetPoolTableName();
        $strQueryType = 'create';
        $isSuccess = parent::createDropTruncateDBSchema($defaultArrTable, $strQueryType, $mixTableName);
        return $isSuccess;
    }
    /**
     *\brief Description
     * - This method will drop relative table of WidgetPool
     * - If table is existed and execute drop failed, it will raised Exception
     *\par Variable
     * - EX : $mixTableName string
     * WP_UPDATE_LOG
     * - EX : $mixTableName array
     * array (
     * 0 => 'WIDGET',
     * 1 => 'WIDGET_CATEGORY'
     * )
     */
    public function dropWidgetPoolDBSchema($mixTableName = null){
        $defaultArrTable = $this->objWidgetPoolFactory->getWidgetPoolOpt()->getWidgetPoolTableName();
        $strQueryType = 'drop';
        $isSuccess = parent::createDropTruncateDBSchema($defaultArrTable, $strQueryType, $mixTableName);
        return $isSuccess;
    }
    /**
     *\brief Description
     * - This method will truncate WidgetPool relative table
     *\par Variable
     * - EX : $mixTableName string
     * WP_UPDATE_LOG
     * - EX : $mixTableName array
     * array (
     * 0 => 'WIDGET',
     * 1 => 'WIDGET_CATEGORY'
     * )
     */
    public function truncateWidgetPoolTable($mixTableName = null){
        $defaultArrTable = $this->objWidgetPoolFactory->getWidgetPoolOpt()->getWidgetPoolTableName();
        $strQueryType = 'truncate';
        $isSuccess = parent::createDropTruncateDBSchema($defaultArrTable, $strQueryType, $mixTableName);
        return $isSuccess;
    }
    /************************************************
     * WIDGET,WIDGET_CATEGORY,WIDGET_CATEGORY_MAPPING Relative API @START
     ***********************************************/
    /**
     *\brief Description
     * - This is the main() method that synchronize All [modX]/widget.xml to DataBase
     * - [modX] represent all widget folder in /path/to/widgetPool/wpCurrent/widget
     */
    public function synWidgetDataAllToDB(){
        $arrDirTmp1 = glob($this->objWidgetPoolManager->getWPHome() . '/widget/*', GLOB_ONLYDIR);
        $arrDirTmp2 = glob($this->objFramework->getDocumentRoot() . '/repository/userGenerated/widget/*', GLOB_ONLYDIR);
        $arrDir = array();
        if((is_array($arrDirTmp1) && $arrDirTmp1) || (is_array($arrDirTmp2) && $arrDirTmp2)){
            $arrDir = array_merge($arrDirTmp1, $arrDirTmp2);
            foreach($arrDir as $strFullPathDir){
                // get modA from /path/to/modA
                $strWidgetName = basename($strFullPathDir);
                //echo 'strDirName: ' . $strWidgetName . '<br />';
                $this->synWidgetDataToDBByWidgetName($strWidgetName);
            }
        }
    }
    /**
     *\brief Description
     * - This method will synchronize $strWidgetName/widget.xml to DB
     * - $strWidgetName is represent a specific widget folder
     * @param string $strWidgetName widget folder name 
     */
    public function synWidgetDataToDBByWidgetName($strWidgetName){
        // get arrDataWidget from widget.xml
        $arrDataWidget = $this->objWidgetPoolManager->getArrDataWidgetByWidgetName($strWidgetName);
        // 1)If not base_widget
        // 2)If widget is compatible with WF
        // syn widget.xml to db
        if((false === $this->isBaseWidget($arrDataWidget)) && (true === $this->isWidgetCompatibleWithWf($arrDataWidget))){
            $widget_id = $this->insertOrUpdateWidgetByArrData($arrDataWidget);
            $arrsDataWidgetCategory = $this->objWidgetPoolManager->getArrsDataWidgetCategoryByWidgetName($strWidgetName);
            $this->insertOrUpdateWidgetCategoryAndMappingByArrsData($widget_id, $arrsDataWidgetCategory);
        }
    }
    /**
     *\brief Description
     * - This method will delete widget from DB
     * - $strWidgetName is represent a specific widget folder
     * @param string $strWidgetName widget folder name 
     */
    public function deleteWidgetDataFromDBByWidgetName($strWidgetName){
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        $objParameter->appendFrom('WIDGET');
        $objParameter->appendSelect('widget_id');
        $objParameter->andWhereEqual('widget_name', $strWidgetName);
        $widget_id = $this->objDataObject->querySelectOneByParameter($objParameter);
        if(false === $widget_id){
            $message = __CLASS__ . '::' . __FUNCTION__ . '()=>SELECT widget_id FROM WIDGET failed! Err Msg:' . $this->objDataObject->getErrMessage();
            throw new WFDbDatabaseObjectException($message);
        }elseif(! $widget_id){
            $message = __CLASS__ . '::' . __FUNCTION__ . '()=>Can\'t find ' . $strWidgetName . ' FROM WIDGET!';
            throw new WFWidgetPoolWidgetPoolDBException($message);
        }
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        $objParameter->appendFrom('WIDGET');
        $objParameter->andWhereEqual('widget_id', $widget_id);
        $isSuccess = $this->objDataObject->queryDeleteByParameter($objParameter);
        if(false === $isSuccess){
            $message = __CLASS__ . '::' . __FUNCTION__ . '()=>DELETE FROM WIDGET WHERE widget_name=' . $strWidgetName . ' failed! Err Msg:' . $this->objDataObject->getErrMessage();
            throw new WFDbDatabaseObjectException($message);
        }
        // Delete Table WIDGET_CATEGORY_MAPPING
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        $objParameter->appendFrom('WIDGET_CATEGORY_MAPPING');
        $objParameter->andWhereEqual('widget_id', $widget_id);
        $isSuccess2 = $this->objDataObject->queryDeleteByParameter($objParameter);
        if(false === $isSuccess2){
            $message = __CLASS__ . '::' . __FUNCTION__ . '()=>DELETE FROM WIDGET_CATEGORY_MAPPING WHERE widget_name=' . $strWidgetName . ' failed! Err Msg:' . $this->objDataObject->getErrMessage();
            throw new WFDbDatabaseObjectException($message);
        }
        return $isSuccess && $isSuccess2;
    }
    /**
     *\brief Description
     * - This method will delete widget from Table WIDGET_CATEGORY_MAPPING
     * - $strWidgetName is represent a specific widget folder
     * @param string $strWidgetName widget folder name 
     */
    /*protected function deleteWidgetCategoryMappingDataFromDBByWidgetName($strWidgetName){
        
    }*/
    /**
     *\brief Description
     * - check is widget belong to base_widget
     * @param array $arrDataWidget
     * @return boolean isBaseWidget
     */
    protected function isBaseWidget($arrDataWidget){
        $ret = (isset($arrDataWidget['widget_type']) && $arrDataWidget['widget_type'] > 0) ? false : true;
        return $ret;
    }
    /**
     *\brief Description
     * - check is widget version is compatible with widget framework version
     * @param array $arrDataWidget
     * @return boolean isWidgetCompatibleWithWf
     */
    public function isWidgetCompatibleWithWf($arrDataWidget){
        $ret = false;
        if(isset($arrDataWidget['widget_min_wf_version'])){
            $version_wf = $this->objConfig->getVersion();
            $widget_min_wf_version = $arrDataWidget['widget_min_wf_version'];
            $isVersionNumberValid = $this->objFramework->getTypeFactory()->getString()->isVersionNumberValid($widget_min_wf_version);
            if(true === $isVersionNumberValid){
                $widget_min_wf_version_float = $this->objFramework->getTypeFactory()->getString()->getVersionFloatByString($widget_min_wf_version);
                $version_wf_float = $this->objFramework->getTypeFactory()->getString()->getVersionFloatByString($version_wf);
                $ret = ($version_wf_float >= $widget_min_wf_version_float) ? true : false;
            }
        }
        return $ret;
    }
    /**
     *\brief Description
     * - This method will synchronize $strPathWidget/widget.xml to DB
     * - $strPathWidget is the PATH of widget folder
     * - EX : $strPathWidget
     * - /Users/jersus/htdocs/CruiseControl/projects/Widget_Framework/TMShare/AJAX-Widget/Dev/AJAX-Widgets-1.7/AJAX-Widgets/src/repository/widgetPool/wpLogId/modFlickr
     * @param string $strWidgetName widget folder name 
     */
    public function synWidgetDataToDBByWidgetPath($strPathWidget){
        $arrDataWidget = $this->objWidgetPoolManager->getArrDataWidgetByWidgetPath($strPathWidget);
        $arrsDataWidgetCategory = $this->objWidgetPoolManager->getArrsDataWidgetCategoryByWidgetPath($strPathWidget);
        $widget_id = $this->insertOrUpdateWidgetByArrData($arrDataWidget);
        $this->insertOrUpdateWidgetCategoryAndMappingByArrsData($widget_id, $arrsDataWidgetCategory);
    }
    /**
     *\brief Description
     * - If Widget existed, update by $arrDataWidget.
     * - If Widget not existed, insert by $arrDataWidget.
     *\par Variable
     * - EX: $arrDataWidget
     * array (
     * 'widget_name' => 'modFlickr',
     * 'widget_version' => '1.0',
     * 'widget_status' => '1',
     * 'widget_min_wf_version' => '2.0',
     * 'user_generated' => NULL,
     * 'icon' => 'wicon_table.gif'
     * )
     * @param array $arrDataWidget
     * @return integer widget_id
     */
    protected function insertOrUpdateWidgetByArrData($arrDataWidget){
        //print_r($arrDataWidget);
        $strWidgetName = isset($arrDataWidget['widget_name']) && $arrDataWidget['widget_name'] ? $arrDataWidget['widget_name'] : '';
        if(! $strWidgetName){
            $message = __CLASS__ . "::" . __FUNCTION__ . "()=>\$arrDataWidget['widget_name'] is required!";
            throw new WFWidgetPoolWidgetPoolDBException($message);
        }
        $strWidgetVersion = isset($arrDataWidget['widget_version']) && $arrDataWidget['widget_version'] ? $arrDataWidget['widget_version'] : '';
        if(! $strWidgetVersion){
            $message = __CLASS__ . "::" . __FUNCTION__ . "()=>\$arrDataWidget['widget_version'] is required!";
            throw new WFWidgetPoolWidgetPoolDBException($message);
        }
        $arrDataWidget['widget_status'] = isset($arrDataWidget['widget_status']) ? $arrDataWidget['widget_status'] : '0';
        $arrDataWidget['user_generated'] = isset($arrDataWidget['user_generated']) ? $arrDataWidget['user_generated'] : '0';
        $isWidgetExisted = $this->isWidgetExistedByWidgetName($strWidgetName);
        if(false === $isWidgetExisted){ //Insert
            $widget_id = $this->insertWidgetByArrData($arrDataWidget);
        }else{ //Update
            $widget_id = $isWidgetExisted;
            $this->updateWidgetByArrData($widget_id, $arrDataWidget);
        }
        return $widget_id;
    }
    /**
     *\brief Description
     * - Update Widget Data by $arrDataWidget.
     *\par Variable
     * - EX: $arrDataWidget
     * array (
     * 'widget_name' => 'modFlickr',
     * 'widget_version' => '1.0',
     * 'widget_status' => '1',
     * 'widget_min_wf_version' => '2.0',
     * 'user_generated' => NULL,
     * 'icon' => 'wicon_table.gif'
     * )
     * @param integer $widget_id
     * @param array $arrDataWidget
     */
    protected function updateWidgetByArrData($widget_id, $arrDataWidget){
        $arrDataWidget = $this->getArrDataWidgetValidByArrData($arrDataWidget);
        if(is_array($arrDataWidget) && $arrDataWidget){
            $objParameter = $this->objWidgetPoolFactory->getParameter();
            $objParameter->appendFrom('WIDGET');
            $widget_status_update = $this->getWidgetStatusUpdateByWidgetId($widget_id, $arrDataWidget['widget_version']);
            if(false !== $widget_status_update){
                $arrDataWidget['widget_status_update'] = $widget_status_update; //0=default,1=new,2=version upgrade
            }
            if(isset($arrDataWidget['widget_id'])){
                unset($arrDataWidget['widget_id']); //Skip PRIMARY KEY
            }
            if(isset($arrDataWidget['widget_version'])){
                $arrDataWidget['widget_version_float'] = $this->objFramework->getTypeFactory()->getString()->getVersionFloatByString($arrDataWidget['widget_version']);
            }
            if(isset($arrDataWidget['widget_min_wf_version'])){
                $arrDataWidget['widget_min_wf_version_float'] = $this->objFramework->getTypeFactory()->getString()->getVersionFloatByString($arrDataWidget['widget_min_wf_version']);
            }
            // update edittime of widget
            $arrDataWidget['edittime'] = (isset($arrDataWidget['edittime']) && $arrDataWidget['edittime']) ? strtotime($arrDataWidget['edittime']) : '';
            if(isset($arrDataWidget['widget_version']) && $arrDataWidget['widget_version']){
                $objParameter = $this->objWidgetPoolFactory->getParameter();
                $objParameter->appendSelect('widget_version_float');
                $objParameter->appendFrom('WIDGET');
                $objParameter->andWhereEqual("widget_id", $widget_id);
                $floatWidgetVersionFloat = $this->objDataObject->querySelectOneByParameter($objParameter);
                // if widget_version in widget.xml is newer than db widget_version
                if($floatWidgetVersionFloat < $arrDataWidget['widget_version']){
                    $arrDataWidget['edittime'] = time();
                }
            }
            if(array_key_exists('edittime', $arrDataWidget) && ! $arrDataWidget['edittime']){ //if edittime is empty, unset to avoid edittime=''
                unset($arrDataWidget['edittime']);
            }
            $objParameter->setAssocData($arrDataWidget);
            $objParameter->andWhereEqual("widget_id", $widget_id);
            $isSuccess = $this->objDataObject->queryUpdateByParameter($objParameter);
            if(false === $isSuccess){
                $message = __CLASS__ . '::' . __FUNCTION__ . '()=>UPDATE WIDGET failed! Err Msg:' . $this->objDataObject->getErrMessage();
                throw new WFDbDatabaseObjectException($message);
            }
            return $isSuccess;
        }
    }
    /**
     *\brief Description
     * - if widget is to be upgrade, widget_status_update=2;
     * - if widget is new from WidgetPool Update, widget_status_update=1;
     * - else if widget is default, widget_status_update=0
     * @param $widget_id
     * @param $strWidgetVersionHasToUpdate
     * @return mix return 2 if widget is upgrade, return 1 if widget is new create
     */
    protected function getWidgetStatusUpdateByWidgetId($widget_id, $strWidgetVersionHasToUpdate){
        $ret = false;
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        $objParameter->appendSelect('widget_version');
        $objParameter->appendFrom('WIDGET');
        $objParameter->andWhereEqual("widget_id", $widget_id);
        $widget_version = $this->objDataObject->querySelectOneByParameter($objParameter);
        if($widget_version){
            if($widget_version < $strWidgetVersionHasToUpdate){
                $ret = '2'; //0=default,1=new,2=version upgrade
            }else{
                $ret = '0';
            }
        }else{
            $ret = '1'; //0=default,1=new,2=version upgrade
        }
        return $ret;
    }
    /**
     *\brief Description
     * - Insert Widget Data by $arrDataWidget.
     *\par Variable
     * - EX: $arrDataWidget
     * array (
     * 'widget_name' => 'modFlickr',
     * 'widget_version' => '1.0',
     * 'widget_status' => '1',
     * 'widget_min_wf_version' => '2.0',
     * 'user_generated' => NULL,
     * 'icon' => 'wicon_table.gif'
     * )
     * @param $arrDataWidget
     * @return mix return lastInsertId of widget_id if insert success, return false if insert fail.
     */
    protected function insertWidgetByArrData($arrDataWidget){
        $ret = false;
        $arrDataWidget = $this->getArrDataWidgetValidByArrData($arrDataWidget);
        if(is_array($arrDataWidget) && $arrDataWidget){
            $objParameter = $this->objWidgetPoolFactory->getParameter();
            $objParameter->appendFrom('WIDGET');
            $strCurrentData = time();
            $arrDataWidget['createtime'] = $strCurrentData;
            //if widget.xml have defined <edittime>2010-11-01 00:00:00</edittime>
            //use 2010-11-01 00:00:00 as edittime
            //else use current server time as edittime
            $arrDataWidget['edittime'] = (isset($arrDataWidget['edittime']) && $arrDataWidget['edittime']) ? strtotime($arrDataWidget['edittime']) : $strCurrentData;
            $arrDataWidget['widget_status_update'] = '1'; //1=new,2=version upgrade
            $arrDataWidget['widget_version_float'] = $this->objFramework->getTypeFactory()->getString()->getVersionFloatByString($arrDataWidget['widget_version']);
            $arrDataWidget['widget_min_wf_version_float'] = $this->objFramework->getTypeFactory()->getString()->getVersionFloatByString($arrDataWidget['widget_min_wf_version']);
            $objParameter->setAssocData($arrDataWidget);
            $this->objDataObject->queryInsertByParameter($objParameter);
            $ret = $this->objDataObject->lastInsertId();
        }
        if(false === $ret){
            $message = __CLASS__ . '::' . __FUNCTION__ . '()=>INSERT WIDGET failed! Err Msg:' . $this->objDataObject->getErrMessage();
            throw new WFDbDatabaseObjectException($message);
        }
        return $ret;
    }
    /**
     *\brief Description
     * - Insert or Update WidgetCategory Data by $arrsDataWidgetCategory.
     *\par Variable
     * - EX $arrDataWidget :
     * Array
     * (
     * [0] => Array
     * (
     * [category_name] => TMCM
     * [min_support_version] => 1.5
     * )
     * [1] => Array
     * (
     * [category_name] => THREAT
     * [min_support_version] => 1.5
     * )
     * ) 
     * @param integer $widget_id
     * @param array $arrsDataWidgetCategory
     */
    protected function insertOrUpdateWidgetCategoryAndMappingByArrsData($widget_id, $arrsDataWidgetCategory){
        if(! (is_array($arrsDataWidgetCategory) && $arrsDataWidgetCategory)){
            return false;
        }
        //Step 1: update Table WIDGET_CATEGORY
        $arrsWidgetCategoryCurrentInsertOrUpdate = array(); //For syn WIDGET_CATEGORY_MAPPING
        foreach($arrsDataWidgetCategory as $arrDataWidgetCategory){
            $strWidgetCategoryName = $arrDataWidgetCategory['category_name'];
            //var_dump($strWidgetCategoryName);
            if(! $strWidgetCategoryName){
                throw new WFWidgetPoolWidgetPoolDBException("category_name is required!");
            }
            $isWidgetCategoryExisted = $this->isWidgetCategoryExistedByCategoryName($strWidgetCategoryName);
            if(false === $isWidgetCategoryExisted){ //Insert
                $category_id = $this->insertWidgetCategoryByArrData($arrDataWidgetCategory);
            }else{ //Update
                $category_id = $isWidgetCategoryExisted;
                $this->updateWidgetCategoryByArrData($category_id, $arrDataWidgetCategory);
            }
            $arrsWidgetCategoryCurrentInsertOrUpdate[$category_id] = $arrDataWidgetCategory;
        }
        //Step 2: update Table WIDGET_CATEGORY_MAPPING
        $this->updateWidgetCategoryMappingByWidgetId($widget_id, $arrsWidgetCategoryCurrentInsertOrUpdate);
         //return $arrsWidgetCategoryCurrentInsertOrUpdate;
    }
    /**
     *\brief Description
     * - Update WidgetCategory Data by $arrsWidgetCategoryCurrentInsertOrUpdate.
     *\par Variable
     * - EX : $arrDataWidget :
     * Array
     * (
     * [0] => Array
     * (
     * [category_name] => TMCM
     * [min_support_version] => 1.5
     * )
     * [1] => Array
     * (
     * [category_name] => THREAT
     * [min_support_version] => 1.5
     * )
     * ) 
     * @param integer $widget_id
     * @param array $arrsWidgetCategoryCurrentInsertOrUpdate This array is used to calculate deletion of TableWidgetCategoryMapping record, 
     * reserve and update category in $arrsWidgetCategoryCurrentInsertOrUpdate, 
     * delete category not in $arrsWidgetCategoryCurrentInsertOrUpdate  .
     */
    protected function updateWidgetCategoryMappingByWidgetId($widget_id, $arrsWidgetCategoryCurrentInsertOrUpdate){
        //Step1: retrieve all category_id that in db, may be need to delete
        $arrWidgetCategoryIdHasToDelete = $this->getArrWidgetCategoryIdByWidgetId($widget_id);
        if(is_array($arrsWidgetCategoryCurrentInsertOrUpdate) && $arrsWidgetCategoryCurrentInsertOrUpdate){
            $isSuccess = true;
            foreach($arrsWidgetCategoryCurrentInsertOrUpdate as $category_id => $arrWidgetCategory){
                $arrValue = array();
                $objParameter = $this->objWidgetPoolFactory->getParameter();
                $objParameter->appendFrom('WIDGET_CATEGORY_MAPPING');
                if(isset($arrWidgetCategoryIdHasToDelete[$category_id])){ //Update if in current db
                    $arrWidgetCategoryMappingValid = $this->getArrDataWidgetCategoryMappingValidByArrData($arrWidgetCategory);
                    if(isset($arrWidgetCategory['min_support_version'])){
                        $arrWidgetCategoryMappingValid['min_support_version'] = $arrWidgetCategory['min_support_version'];
                        $arrWidgetCategoryMappingValid['min_support_version_float'] = $this->objFramework->getTypeFactory()->getString()->getVersionFloatByString($arrWidgetCategoryMappingValid['min_support_version']);
                    }
                    $arrWidgetCategoryMappingValid['edittime'] = time();
                    $objParameter->setAssocData($arrWidgetCategoryMappingValid);
                    $objParameter->andWhereEqual("widget_id", $widget_id);
                    $objParameter->andWhereEqual("category_id", $category_id);
                    $isSuccess2 = $this->objDataObject->queryUpdateByParameter($objParameter);
                    unset($arrWidgetCategoryIdHasToDelete[$category_id]); // This category_id no need to delete
                }else{ //Insert If not in current db
                    $arrWidgetCategoryMappingValid = array();
                    $arrWidgetCategoryMappingValid['widget_id'] = $widget_id;
                    $arrWidgetCategoryMappingValid['category_id'] = $category_id;
                    if(isset($arrWidgetCategory['min_support_version'])){
                        $arrWidgetCategoryMappingValid['min_support_version'] = $arrWidgetCategory['min_support_version'];
                        $arrWidgetCategoryMappingValid['min_support_version_float'] = $this->objFramework->getTypeFactory()->getString()->getVersionFloatByString($arrWidgetCategoryMappingValid['min_support_version']);
                    }
                    $arrWidgetCategoryMappingValid['createtime'] = time();
                    $objParameter->setAssocData($arrWidgetCategoryMappingValid);
                    $isSuccess2 = $this->objDataObject->queryInsertByParameter($objParameter);
                }
                $isSuccess = $isSuccess && $isSuccess2;
            }
            if(false === $isSuccess){
                $message = __CLASS__ . '::' . __FUNCTION__ . '()=>UPDATE/INSERT WIDGET_CATEGORY_MAPPING failed! Err Msg:' . $this->objDataObject->getErrMessage();
                throw new WFDbDatabaseObjectException($message);
            }
        }
        //Step2: Delete the category_id that have to delete
        if(is_array($arrWidgetCategoryIdHasToDelete) && $arrWidgetCategoryIdHasToDelete){
            $objParameter = $this->objWidgetPoolFactory->getParameter();
            $objParameter->appendFrom('WIDGET_CATEGORY_MAPPING');
            $objParameter->andWhereEqual("widget_id", $widget_id);
            $objParameter->andWhereIn('category_id', $arrWidgetCategoryIdHasToDelete);
            $isSuccess = $this->objDataObject->queryDeleteByParameter($objParameter);
            if(false === $isSuccess){
                $message = __CLASS__ . '::' . __FUNCTION__ . '()=>DELETE WIDGET_CATEGORY WHERE widget_id=? failed! Err Msg:' . $this->objDataObject->getErrMessage();
                throw new WFDbDatabaseObjectException($message);
            }
        }
    }
    /**
     *\brief Description
     * - Update WidgetCategory Data by $arrDataWidgetCategory.
     * - EX : $arrDataWidget :
     * Array
     * (
     * [0] => Array
     * (
     * [category_name] => TMCM
     * [min_support_version] => 1.5
     * )
     * [1] => Array
     * (
     * [category_name] => THREAT
     * [min_support_version] => 1.5
     * )
     * ) 
     * @param integer $category_id
     * @param array $arrDataWidgetCategory  
     */
    protected function updateWidgetCategoryByArrData($category_id, $arrDataWidgetCategory){
        $arrDataWidgetCategory = $this->getArrDataWidgetCategoryValidByArrData($arrDataWidgetCategory);
        if(is_array($arrDataWidgetCategory) && $arrDataWidgetCategory){
            $objParameter = $this->objWidgetPoolFactory->getParameter();
            $objParameter->appendFrom('WIDGET_CATEGORY');
            //Avoid update category_id
            if(isset($arrDataWidgetCategory['category_id'])){
                unset($arrDataWidgetCategory['category_id']); //Skip PRIMARY KEY
            }
            //trim category_name
            if(isset($arrDataWidgetCategory['category_name'])){
                $arrDataWidgetCategory['category_name'] = trim($arrDataWidgetCategory['category_name']);
            }
            //var_dump($arrDataWidgetCategory);
            if(! isset($arrDataWidgetCategory['edittime'])){
                $arrDataWidgetCategory['edittime'] = time();
            }
            $objParameter->setAssocData($arrDataWidgetCategory);
            $objParameter->andWhereEqual('category_id', $category_id);
            $isSuccess = $this->objDataObject->queryUpdateByParameter($objParameter);
            if(false === $isSuccess){
                $message = __CLASS__ . '::' . __FUNCTION__ . '()=>UPDATE WIDGET_CATEGORY assocData WHERE category_id=? failed! Err Msg:' . $this->objDataObject->getErrMessage();
                throw new WFDbDatabaseObjectException($message);
            }
        }
    }
    /**
     *\brief Description
     * - Insert WidgetCategory Data by $arrDataWidgetCategory.
     * - EX : $arrDataWidget :
     * Array
     * (
     * [0] => Array
     * (
     * [category_name] => TMCM
     * [min_support_version] => 1.5
     * )
     * [1] => Array
     * (
     * [category_name] => THREAT
     * [min_support_version] => 1.5
     * )
     * ) 
     * @param array $arrDataWidgetCategory  
     * @return mix return lastInsertId of category_id if insert success, return false if insert fail.
     */
    protected function insertWidgetCategoryByArrData($arrDataWidgetCategory){
        $ret = false;
        // Verify $arrDataWidgetCategory is integrity
        $arrDataWidgetCategory = $this->getArrDataWidgetCategoryValidByArrData($arrDataWidgetCategory);
        if(is_array($arrDataWidgetCategory) && $arrDataWidgetCategory){
            $objParameter = $this->objWidgetPoolFactory->getParameter();
            $objParameter->appendFrom('WIDGET_CATEGORY');
            if(isset($arrDataWidgetCategory['category_id'])){
                unset($arrDataWidgetCategory['category_id']); //Skip PRIMARY KEY of TableWidgetCategory
            }
            //trim category_name
            if(isset($arrDataWidgetCategory['category_name'])){
                $arrDataWidgetCategory['category_name'] = trim($arrDataWidgetCategory['category_name']);
            }
            $arrDataWidgetCategory['createtime'] = time();
            $objParameter->setAssocData($arrDataWidgetCategory);
            $this->objDataObject->queryInsertByParameter($objParameter);
            $ret = $this->objDataObject->lastInsertId();
        }
        if(false === $ret){
            $message = "INSERT WIDGET_CATEGORY failed! Err Msg:" . $this->objDataObject->getErrMessage();
            throw new WFDbDatabaseObjectException($message);
        }
        return $ret;
    }
    /**
     *\brief Description
     * - This method will get $arrWidgetCategoryId from db by $widget_id
     * - EX : $arrWidgetCategoryId :
     * Array (
     * [0] => 1,
     * [1] => 2
     * )
     * @param $widget_id
     * @return array
     */
    protected function getArrWidgetCategoryIdByWidgetId($widget_id){
        /*$sql="SELECT category_id
              FROM WIDGET_CATEGORY_MAPPING
              WHERE widget_id = :widget_id";
        $sqlvalues[':widget_id'] = $widget_id;
        $arrsData = $this->objDataObject->query($sql,$sqlvalues);*/
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        $objParameter->appendFrom('WIDGET_CATEGORY_MAPPING');
        $objParameter->andWhereEqual("widget_id", $widget_id);
        $objParameter->appendSelect('category_id');
        $arrsData = $this->objDataObject->querySelectAllByParameter($objParameter);
        if(false === $arrsData){
            $message = __CLASS__ . '::' . __FUNCTION__ . '()=>SELECT category_id FROM WIDGET WHERE widget_id=? failed! Err Msg:' . $this->objDataObject->getErrMessage();
            throw new WFDbDatabaseObjectException($message);
        }
        $ret = array();
        if(! is_array($arrsData) && $arrsData){
            return $ret;
        }
        foreach($arrsData as $arrData){
            $ret[$arrData['category_id']] = $arrData['category_id'];
        }
        return $ret;
    }
    /**
     *\brief Description
     * - This method will verify the integrity of $arrDataWidget
     * @param $arrDataWidget
     * @return array
     */
    protected function getArrDataWidgetValidByArrData($arrDataWidget){
        $ret = array();
        if(is_array($arrDataWidget) && $arrDataWidget){
            $arrTableSchemaColumnValid = $this->objWidgetPoolFactory->getWidgetPoolOpt()->getTableSchemaColumnWidget();
            foreach($arrDataWidget as $strColumnName => $mixColumnValue){
                if(true === in_array($strColumnName, $arrTableSchemaColumnValid)){
                    $ret[$strColumnName] = $mixColumnValue;
                }
            }
        }
        return $ret;
    }
    /**
     *\brief Description
     * - This method will verify the integrity of $arrDataWidgetCategory
     * @param $arrDataWidgetCategory
     * @return array
     */
    protected function getArrDataWidgetCategoryValidByArrData($arrDataWidgetCategory){
        $ret = array();
        if(is_array($arrDataWidgetCategory) && $arrDataWidgetCategory){
            $arrTableSchemaColumnValid = $this->objWidgetPoolFactory->getWidgetPoolOpt()->getTableSchemaColumnWidgetCategory();
            foreach($arrDataWidgetCategory as $strColumnName => $mixColumnValue){
                if(true === in_array($strColumnName, $arrTableSchemaColumnValid)){
                    $ret[$strColumnName] = $mixColumnValue;
                }
            }
        }
        return $ret;
    }
    /**
     *\brief Description
     * - This method will verify the integrity of $arrDataWidgetCategory
     * @param $arrDataWidgetCategory
     * @return array
     */
    protected function getArrDataWidgetCategoryMappingValidByArrData($arrDataWidgetCategory){
        $ret = array();
        if(is_array($arrDataWidgetCategory) && $arrDataWidgetCategory){
            $arrTableSchemaColumnValid = $this->objWidgetPoolFactory->getWidgetPoolOpt()->getTableSchemaColumnWidgetCategoryMapping();
            foreach($arrDataWidgetCategory as $strColumnName => $mixColumnValue){
                if(true === in_array($strColumnName, $arrTableSchemaColumnValid)){
                    $ret[$strColumnName] = $mixColumnValue;
                }
            }
        }
        return $ret;
    }
    /**
     *\brief Description
     * - This method will check is the specific widget is existed in TableWidget 
     * @param $strWidgetName
     * @return mix return false is not existed in TableWidget, return widget_id is the widget exist in TableWidget 
     */
    protected function isWidgetExistedByWidgetName($strWidgetName){
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        $objParameter->appendSelect('widget_id');
        $objParameter->appendFrom("WIDGET");
        $objParameter->andWhereEqual("widget_name", $strWidgetName);
        $widget_id = $this->objDataObject->querySelectOneByParameter($objParameter);
        if(false === $widget_id){
            $message = __CLASS__ . '::' . __FUNCTION__ . '()=>SELECT widget_id FROM WIDGET WHERE widget_name=? fetchOne failed! Err Msg:' . $this->objDataObject->getErrMessage();
            throw new WFDbDatabaseObjectException($message);
        }
        return $widget_id ? $widget_id : false;
    }
    /**
     *\brief Description
     * - This method will check is the specific WIDGET_CATEGORY is existed in TableWidgetCategory 
     * @param $strCategoryName
     * @return mix return false is not existed in TableWidgetCategory, return category_id is the widget exist in TableWidgetCategory 
     */
    protected function isWidgetCategoryExistedByCategoryName($strCategoryName){
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        $objParameter->appendSelect('category_id');
        $objParameter->appendFrom('WIDGET_CATEGORY');
        $objParameter->andWhereEqual("category_name", $strCategoryName);
        $category_id = $this->objDataObject->querySelectOneByParameter($objParameter);
        if(false === $category_id){
            $message = __CLASS__ . '::' . __FUNCTION__ . '()=>SELECT category_id FROM WIDGET_CATEGORY WHERE category_name=? fetchOne failed! Err Msg:' . $this->objDataObject->getErrMessage();
            throw new WFDbDatabaseObjectException($message);
        }
        return $category_id ? $category_id : false;
    }
    /************************************************
     * WIDGET,WIDGET_CATEGORY,WIDGET_CATEGORY_MAPPING Relative API @END
     ***********************************************/
    /**
     *\brief Description
     * - If WP_UPDATE_FILTER record existed, update by $arrData.
     * - If WP_UPDATE_FILTER record not existed, insert by $arrData.
     * - EX : $arrData
     * Array
     * (
     * [file_interface] => synWidgetXMLToDB.php
     * [filter_target] => IDF
     * [filter_condition] => 2.0
     * )
     * @param array $arrData
     * @return filter_id
     */
    public function insertOrUpdateFilterByArrData($arrData){
        $filter_key = $this->objWidgetPoolFactory->getWidgetPoolInterface()->getFilterKeyHashByMix($arrData);
        $isRowExisted = $this->isFilterExistedByArrData($arrData);
        //var_dump($filter_key,$isRowExisted);
        if(! $isRowExisted){ //Insert to db
            $arrData['filter_key'] = $filter_key;
            $filter_id = $this->insertFilterByArrData($arrData);
        }else{ //Update $filter_id
            $filter_id = $this->getFilterIdByArrData($arrData);
            $this->updateFilterByArrData($filter_id, $arrData);
        }
        return $filter_id;
    }
    /**
     *\brief Description
     * - check is filter record is existed in Table WP_UPDATE_FILTER
     * - EX : $arrData
     * Array
     * (
     * [file_interface] => synWidgetXMLToDB.php
     * [filter_target] => IDF
     * [filter_condition] => 2.0
     * )
     * @param array $arrDataWidget
     */
    protected function isFilterExistedByArrData($arrData){
        $filter_key = $this->objWidgetPoolFactory->getWidgetPoolInterface()->getFilterKeyHashByMix($arrData);
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        //$objParameter->setPrimaryKey('filter_key'); //for COUNT(filter_key)
        $objParameter->setPrimaryKey('filter_id');
        $objParameter->appendFrom('WP_UPDATE_FILTER');
        $objParameter->andWhereEqual("filter_key", $filter_key);
        $isRowExisted = $this->objDataObject->querySelectCountByParameter($objParameter);
        //var_dump($filter_key,$isRowExisted);
        if(false === $isRowExisted){
            $message = __CLASS__ . '::' . __FUNCTION__ . '()=>SELECT COUNT FROM WP_UPDATE_FILTER WHERE filter_key=? fetchOne failed! Err Msg:' . $this->objDataObject->getErrMessage();
            throw new WFDbDatabaseObjectException($message);
        }
        return $isRowExisted ? true : false;
    }
    /**
     *\brief Description
     * - get WP_UPDATE_FILTER.filter_id by $arrData
     * - EX : $arrData
     * Array
     * (
     * [file_interface] => synWidgetXMLToDB.php
     * [filter_target] => IDF
     * [filter_condition] => 2.0
     * )
     * @param array $arrDataWidget
     */
    protected function getFilterIdByArrData($arrData){
        $filter_key = $this->objWidgetPoolFactory->getWidgetPoolInterface()->getFilterKeyHashByMix($arrData);
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        //$objParameter->setPrimaryKey('filter_key'); //for COUNT(filter_key)
        $objParameter->appendSelect('filter_id');
        $objParameter->appendFrom('WP_UPDATE_FILTER');
        $objParameter->andWhereEqual("filter_key", $filter_key);
        $isRowExisted = $this->objDataObject->querySelectOneByParameter($objParameter);
        //var_dump($filter_key,$isRowExisted);
        if(false === $isRowExisted){
            $message = __CLASS__ . '::' . __FUNCTION__ . '()=>SELECT filter_id FROM WP_UPDATE_FILTER WHERE filter_key=? fetchOne failed! Err Msg:' . $this->objDataObject->getErrMessage();
            throw new WFDbDatabaseObjectException($message);
        }
        return $isRowExisted;
    }
    /**
     *\brief Description
     * - Update WP_UPDATE_FILTER record by assocData WHERE WP_UPDATE_FILTER.filter_id=$filter_id
     * - EX : $arrData
     * Array
     * (
     * [file_interface] => synWidgetXMLToDB.php
     * [filter_target] => IDF
     * [filter_condition] => 2.0
     * )
     * @param integer $filter_id
     * @param array $arrDataWidget
     */
    protected function updateFilterByArrData($filter_id, $arrData){
        $arrData['edittime'] = time();
        $arrData['filter_key'] = $this->objWidgetPoolFactory->getWidgetPoolInterface()->getFilterKeyHashByMix($arrData);
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        $objParameter->appendFrom('WP_UPDATE_FILTER');
        $objParameter->setAssocData($arrData);
        $objParameter->andWhereEqual("filter_id", $filter_id);
        $isSuccess = $this->objDataObject->queryUpdateByParameter($objParameter);
        if(false === $isSuccess){
            $message = __CLASS__ . '::' . __FUNCTION__ . '()=>UPDATE WP_UPDATE_FILTER SET assocData WHERE filter_id=? failed! Err Msg:' . $this->objDataObject->getErrMessage();
            throw new WFDbDatabaseObjectException($message);
        }
        return $isSuccess;
    }
    /**
     *\brief Description
     * - Insert WP_UPDATE_FILTER record by assocData
     * - EX : $arrData
     * Array
     * (
     * [file_interface] => synWidgetXMLToDB.php
     * [filter_target] => IDF
     * [filter_condition] => 2.0
     * )
     * @param array $arrData
     * @return mix If insert success return lastInsert filter_id, if failed return false
     */
    protected function insertFilterByArrData($arrData){
        $arrData['filter_key'] = $this->objWidgetPoolFactory->getWidgetPoolInterface()->getFilterKeyHashByMix($arrData);
        $arrData['createtime'] = time();
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        $objParameter->appendFrom('WP_UPDATE_FILTER');
        $objParameter->setAssocData($arrData);
        $isSuccess = $this->objDataObject->queryInsertByParameter($objParameter);
        if(false === $isSuccess){
            $message = __CLASS__ . '::' . __FUNCTION__ . '()=>INSERT WP_UPDATE_FILTER failed! Err Msg:' . $this->objDataObject->getErrMessage();
            throw new WFDbDatabaseObjectException($message);
        }
        $lastInsertId = $this->objDataObject->lastInsertId();
        return $lastInsertId;
    }
    /**
     *\brief Description
     * - This is the main() method turn on WIDGET.widget_status which widget in specify category of version
     * @param string $strCategory
     * @param float $numberVersion
     */
    public function turnOnWidgetOfCategoryByVersion($strCategory, $numberVersion){
        $widget_status = '1';
        $ret = $this->turnWidgetOfCategoryByVersion($strCategory, $numberVersion, $widget_status);
        return $ret;
    }
    /**
     *\brief Description
     * - This is the main() method turn off WIDGET.widget_status which widget in specify category of version
     * @param string $strCategory
     * @param float $numberVersion
     */
    public function turnOffWidgetOfCategoryByVersion($strCategory, $numberVersion){
        $widget_status = '0';
        $ret = $this->turnWidgetOfCategoryByVersion($strCategory, $numberVersion, $widget_status);
        return $ret;
    }
    /**
     *\brief Description
     * - Check is turnOn command line
     * - EX : php /path/to/interface_request.php turnOnWidgetOfCategoryByVersion.php IDF 2.0
     */
    private function isTurnOnCommand($widget_status){
        return $widget_status ? true : false;
    }
    /**
     *\brief Description
     * - Check is turnOff command line
     * - EX : php /path/to/interface_request.php turnOffWidgetOfCategoryByVersion.php IDF 2.0
     */
    private function isTurnOffCommand($widget_status){
        return $widget_status ? false : true;
    }
    /**
     *\brief Description
     * - This is the main() method turn on or turn off WIDGET.widget_status which widget in specify category of version
     * @param string $strCategory
     * @param float $numberVersion
     * @param integer $widget_status
     */
    protected function turnWidgetOfCategoryByVersion($strCategory, $numberVersion, $widget_status){
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        $objParameter->appendSelect("m.*");
        $objParameter->appendFrom('WIDGET m,WIDGET_CATEGORY mc,WIDGET_CATEGORY_MAPPING mcm');
        $objParameter->andWhereEqual("m.widget_id=mcm.widget_id");
        $objParameter->andWhereEqual("mc.category_id=mcm.category_id");
        $objParameter->andWhereEqual("mc.category_name", $strCategory);
        // turn 1.1.12345 to float
        $numberVersion = $this->objFramework->getTypeFactory()->getString()->getVersionFloatByString($numberVersion);
        $objParameter->andWhereLte("mcm.min_support_version_float", $numberVersion);
        // min_support_version_float must > 0
        $objParameter->andWhereGt("mcm.min_support_version_float", 0);
        // If turnOn, only turnOn widget WHERE widget_status=off
        // If turnOff, only turnOff widget WHERE widget_status=on
        $widget_status_where = $widget_status ? '0' : '1';
        $objParameter->andWhereEqual("m.widget_status", $widget_status_where);
        $arrsData = $this->objDataObject->querySelectAllByParameter($objParameter);
        mydebug_log(basename(__FILE__) . ':' . $this->objFramework->getVarLog($this->objDataObject->queryInfoByParameter($objParameter)));
        if(false === $arrsData){
            $message = __CLASS__ . '::' . __FUNCTION__ . '()=>SELECT widget_id FROM WIDGET,WIDGET_CATEGORY,WIDGET_CATEGORY_MAPPING WHERE category_name=? AND min_support_version_float<=? have to turn on/off failed! Err Msg:' . $this->objDataObject->getErrMessage();
            throw new WFDbDatabaseObjectException($message);
        }elseif(! (is_array($arrsData) && $arrsData)){
            return true;
        }
        $arrWidgetIdHaveToUpdate = array();
        $arrWidgetNameHaveToDeleteFromTab = array();
        foreach($arrsData as $arrData){
            if($this->isTurnOnCommand($widget_status)){ //check is widget_version compatible with WF version
                if($this->isWidgetCompatibleWithWf($arrData)){ // if is turn on and is compatible with WF version
                    $arrWidgetIdHaveToUpdate[$arrData['widget_id']] = $arrData['widget_id'];
                }
            }else{ //if execute interface turnOnWidget command line
                $arrWidgetIdHaveToUpdate[$arrData['widget_id']] = $arrData['widget_id']; //does not need to check version compatible between widget and WidgetFramework
                $arrWidgetNameHaveToDeleteFromTab[$arrData['widget_name']] = $arrData['widget_name'];
            }
        }
        $isSuccess = true;
        // if $arrWidgetIdHaveToUpdate is empty! Do not execute UPDATE statement
        if(! (is_array($arrWidgetIdHaveToUpdate) && $arrWidgetIdHaveToUpdate)){
            return $isSuccess;
        }
        $assocsBeforeUpdateWidgetsFromTableWpUpdateLog = $this->objFramework->getWidgetPoolFactory()->getWidgetPoolManager()->getAssocsBeforeUpdateWidgetsFromTableWpUpdateLog();
        // Start to sort out type of variable
        // one variable is $arrWidgetIdHaveToUpdate and edittime is have to update
        // another variable is $arrWidgetIdHaveToUpdate and edittime is do not need update
        $arrWidgetIdHaveToUpdateAndEdittimeUpdate = array();
        $arrWidgetIdHaveToUpdateAndEdittimeDoNotUpdate = array();
        foreach($arrWidgetIdHaveToUpdate as $strWidgetIdHaveToUpdate){
            if(isset($assocsBeforeUpdateWidgetsFromTableWpUpdateLog[$strWidgetIdHaveToUpdate])){
                if(isset($assocsBeforeUpdateWidgetsFromTableWpUpdateLog[$strWidgetIdHaveToUpdate]['widget_status']) && $widget_status == $assocsBeforeUpdateWidgetsFromTableWpUpdateLog[$strWidgetIdHaveToUpdate]['widget_status']){
                    $arrWidgetIdHaveToUpdateAndEdittimeDoNotUpdate[$strWidgetIdHaveToUpdate] = $strWidgetIdHaveToUpdate;
                }else{
                    $arrWidgetIdHaveToUpdateAndEdittimeUpdate[$strWidgetIdHaveToUpdate] = $strWidgetIdHaveToUpdate;
                }
            }else{
                $arrWidgetIdHaveToUpdateAndEdittimeUpdate[$strWidgetIdHaveToUpdate] = $strWidgetIdHaveToUpdate;
            }
        }
        mydebug_log($this->objFramework->getVarLog($arrWidgetIdHaveToUpdateAndEdittimeUpdate));
        mydebug_log($this->objFramework->getVarLog($arrWidgetIdHaveToUpdateAndEdittimeDoNotUpdate));
        $arrsForLoopVariable = array();
        $arrsForLoopVariable[] = array('variable_name' => 'arrWidgetIdHaveToUpdateAndEdittimeUpdate', 'edittime' => time());
        $arrsForLoopVariable[] = array('variable_name' => 'arrWidgetIdHaveToUpdateAndEdittimeDoNotUpdate', 'edittime' => '');
        foreach($arrsForLoopVariable as $arrForLoopVariable){
            $objParameter = $this->objWidgetPoolFactory->getParameter();
            $objParameter->appendFrom('WIDGET');
            $arrWidgetIdHaveToUpdate = ${$arrForLoopVariable['variable_name']};
            if(! (is_array($arrWidgetIdHaveToUpdate) && $arrWidgetIdHaveToUpdate)){
                continue;
            }
            $objParameter->andWhereIn("widget_id", $arrWidgetIdHaveToUpdate);
            //Update edittime
            $assocData = array();
            $assocData['widget_status'] = $widget_status;
            $edittime = isset(${$arrForLoopVariable['edittime']}) ? ${$arrForLoopVariable['edittime']} : '';
            if($edittime){
                $assocData['edittime'] = $edittime;
            }
            $objParameter->setAssocData($assocData);
            $isSuccess = $this->objDataObject->queryUpdateByParameter($objParameter);
            mydebug_log(basename(__FILE__) . ':' . $this->objFramework->getVarLog($this->objDataObject->queryInfoByParameter($objParameter)));
            if(false === $isSuccess){
                $message = __CLASS__ . '::' . __FUNCTION__ . '()=>UPDATE WIDGET SET assocData WHERE widget_id in ? have to turn on/off failed! Err Msg:' . $this->objDataObject->getErrMessage();
                throw new WFDbDatabaseObjectException($message);
            }
        }
        // Delete widget from tab
        $this->deleteWidgetFromTabByArrWidgetName($arrWidgetNameHaveToDeleteFromTab);
        return $isSuccess ? true : false;
    }
    /**
     *\brief Description
     * - Get $arrUserGeneratedInfo of user_generated
     *\par Variable 
     * - EX : $arrUserGeneratedInfo
     * array(
     * 'modFlickr'=>'0',
     * 'modSearch'=>'0'
     * )
     * @return array $UserGeneratedInfo
     */
    public function getUserGeneratedInfoOfWidget(){
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        $objParameter->appendFrom('WIDGET');
        $objParameter->andWhereEqual('widget_status', '1');
        $arrsData = $this->objDataObject->querySelectAllByParameter($objParameter);
        if(false === $arrsData){
            $message = __CLASS__ . '::' . __FUNCTION__ . '()=>SELECT WIDGET for UserGenerated failed! Err Msg:' . $this->objDataObject->getErrMessage();
            throw new WFDbDatabaseObjectException($message);
        }
        $ret = array();
        if(! is_array($arrsData) && ($arrsData || empty($arrsData[0]))){
            return $ret;
        }
        foreach($arrsData as $arrData){
            $ret[$arrData['widget_name']] = $arrData['user_generated'];
        }
        return $ret;
    }
    /**
     *\brief Description
     * - Delete widget from Tab
     * - If failed, will raise an exception
     * @param string $strWidgetName
     */
    public function deleteWidgetFromTabByArrWidgetName($arrWidgetName){
        if(is_array($arrWidgetName) && $arrWidgetName){
            foreach($arrWidgetName as $strWidgetName){
                $this->deleteWidgetFromTabByWidgetName($strWidgetName);
            }
        }
    }
    /**
     *\brief Description
     * - Delete widget from Tab
     * - If failed, will raise an exception
     * @param string $strWidgetName
     */
    public function deleteWidgetFromTabByWidgetName($strWidgetName){
        //Step1 : get modname of $strWidgetName
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        $objParameter->appendFrom("WIDGET");
        $objParameter->andWhereEqual("widget_name", $strWidgetName);
        $arrDataWidget = $this->objDataObject->querySelectRowByParameter($objParameter);
        if(! $arrDataWidget){
            $strMsg = __CLASS__ . '::' . __FUNCTION__ . '()=>' . $strWidgetName . ' is not in Table WIDGET!';
            throw new WFWidgetPoolWidgetPoolDBException($strMsg);
        }
        //$ret_isSuccess = true;
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        $objParameter->appendFrom("userdata");
        $objParameter->andWhereEqual("modname", $arrDataWidget['modname']);
        $objParameter->andWhereEqual("widget_key", $arrDataWidget['widget_key']);
        $isSuccess = $this->objDataObject->queryDeleteByParameter($objParameter);
        if(false === $isSuccess){
            $message = __CLASS__ . '::' . __FUNCTION__ . '()=>SELECT * FROM userdata WHERE modname=? failed! Err Msg:' . $this->objDataObject->getErrMessage();
            throw new WFDbDatabaseObjectException($message);
        }
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        $objParameter->appendFrom("users");
        $arrsDataUser = $this->objDataObject->querySelectAllByParameter($objParameter);
        //var_dump($arrsDataUser);
        if(false === $arrsDataUser){
            $message = __CLASS__ . '::' . __FUNCTION__ . '()=>SELECT * FROM users failed! Err Msg:' . $this->objDataObject->getErrMessage();
            throw new WFDbDatabaseObjectException($message);
        }
        if(is_array($arrsDataUser) && $arrsDataUser){
            foreach($arrsDataUser as $arrDataUser){
                if(! empty($arrDataUser['udata'])){
                    //$arrDataUdataAfterDelete = array();
                    //Step 1: transform jsonUdata to arrsUdata
                    $arrDataUdataBeforeDelete = $this->getArrsUdataByJsonUdata($arrDataUser['udata']);
                    //Step 2: delete specify widget from arrsUdata
                    $strModname = isset($arrDataWidget['modname']) ? $arrDataWidget['modname'] : '';
                    $widget_key = isset($arrDataWidget['widget_key']) ? $arrDataWidget['widget_key'] : '';
                    $arrDataUdataAfterDelete = $this->deleteWidgetFromArrsUdataByModnameAndKey($strModname, $widget_key, $arrDataUdataBeforeDelete);
                    //Step 3: after delete, transform arrsUdata to jsonUdata
                    $jsonUdataAfterDelete = $this->getJsonUdataByArrsUdata($arrDataUdataAfterDelete);
                    //Step 4: save data to user record
                    $assocData = array();
                    $assocData['udata'] = $jsonUdataAfterDelete;
                    $objParameter = $this->objWidgetPoolFactory->getParameter();
                    $objParameter->appendFrom('users');
                    $objParameter->andWhereEqual('id', $arrDataUser['id']);
                    $objParameter->setAssocData($assocData);
                    $isSuccess = $this->objDataObject->queryUpdateByParameter($objParameter);
                    if(false === $isSuccess){
                        $message = __CLASS__ . '::' . __FUNCTION__ . '()=>UPDATE users SET udata=? WHERE id=? failed! Err Msg:' . $this->objDataObject->getErrMessage();
                        throw new WFDbDatabaseObjectException($message);
                    }
                }
            }
        }
    }
    /**
     *\brief Description
     * - Get WIDGET.modname by $strWidgetName
     */
    /*protected function getModnameByWidgetName($strWidgetName){
        $arrDataWidget = $this->objWidgetPoolFactory->getWidgetPoolManager()->getArrDataByWidgetName($strWidgetName);
        return isset($arrDataWidget['modname']) ? $arrDataWidget['modname'] : '';
    }*/
    /**
     *\brief Description
     * - transform $jsonUdata to $arrsDataUdata
     * @param json $jsonUdata
     * @return array $arrsDataUdata
     */
    protected function getArrsUdataByJsonUdata($jsonUdata){
        $arrsDataUdata = json_decode($jsonUdata, true);
        return $arrsDataUdata;
    }
    /**
     *\brief Description
     * - transform $arrsUdata to $jsonUdata 
     * @param array $arrsDataUdata
     * @return json $jsonUdata
     */
    protected function getJsonUdataByArrsUdata($arrsUdata){
        $jsonDataUdata = json_encode($arrsUdata);
        return $jsonDataUdata;
    }
    /**
     *\brief Description
     * - Delete specify widget from $arrsDataUdata[users.jsonUdata]
     * @param array $arrsDataUdata $arrsDataUdata after delete specify widget
     */
    protected function deleteWidgetFromArrsUdataByModnameAndKey($strModname, $widget_key, $arrsDataUdata){
        $ret = array();
        if(! $strModname){
            return $arrsDataUdata;
        }
        $ret = array();
        if(is_array($arrsDataUdata) && $arrsDataUdata){
            $arrsDataUdataForLoop = $arrsDataUdata;
            foreach($arrsDataUdataForLoop as $key_loop => $arrDataUdata){
                $widgetKeyUdata = isset($arrDataUdata['widget_key']) ? $arrDataUdata['widget_key'] : '';
                $modnameUdata = isset($arrDataUdata['modname']) ? $arrDataUdata['modname'] : '';
                if(! ($strModname == $modnameUdata && $widget_key == $widgetKeyUdata)){
                    $ret[] = $arrDataUdata;
                }
            }
        }
        return $ret;
    }
    /**
     *\brief Description
     * - initial WidgetPool data
     * - WP_UPDATE_LOG original Data as below:
     * log_id=1
     * status=1
     * fail_point=0
     * createtime=now()
     */
    public function initWidgetPoolDBData(){
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        $objParameter->appendFrom('WP_UPDATE_LOG');
        $objParameter->setPrimaryKey('log_id');
        $objParameter->andWhereEqual('log_id', '1');
        $isExisted = $this->objDataObject->querySelectCountByParameter($objParameter);
        $assocData = array();
        $assocData['status'] = '1'; //success
        $assocData['fail_point'] = '0';
        $assocData['createtime'] = time();
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        $objParameter->appendFrom('WP_UPDATE_LOG');
        $objParameter->setAssocData($assocData);
        if(! $isExisted){ //INSERT
            $this->objDataObject->queryInsertByParameter($objParameter);
        }else{ //UPDATE
            $objParameter->andWhereEqual('log_id', '1');
            $assocData['edittime'] = time();
            $this->objDataObject->queryUpdateByParameter($objParameter);
        }
    }
    /**
     *\brief Description
     * - This method will get current turn on category in WP_UPDATE_FILTER
     * @return array $assocData array('WidgetFramework'=>'2.0','IDF'=>'3.0')
     */
    public function getAssocCurrentTurnedOnCategoryInfo($strCategoryName = null){
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        $objParameter->appendFrom('WP_UPDATE_FILTER');
        $objParameter->andWhereEqual('file_interface', 'turnOnWidgetOfCategoryByVersion.php');
        if($strCategoryName){
            $objParameter->andWhereEqual('filter_target', $strCategoryName);
        }
        $arrsData = $this->objWidgetPoolFactory->getDataObject()->querySelectAllByParameter($objParameter);
        //var_dump($this->objWidgetPoolFactory->getDataObject()->queryInfoByParameter($objParameter));
        $ret = array();
        if(is_array($arrsData) && $arrsData){
            foreach($arrsData as $arrData){
                $ret[$arrData['filter_target']] = $arrData['filter_condition'];
            }
        }
        return $ret;
    }
    /**
     *\brief Description
     * - This method will get arrsData for widgetList.php
     * - Example as below:
     * - $arrsDataByWidgetName[] = array('widget_id'=>'1','category'=>'WidgetFramework,IDF'...);
     * - $arrsDataByWidgetName[] = array('widget_id'=>'2','category'=>'WidgetFramework'...);
     * @return array $arrsData
     */
    public function getArrsDataWidgetList(){
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        $objParameter->appendSelect("mc.category_name AS category,m.widget_name AS name,m.modname,m.icon,m.icon_preview,m.edittime AS lastupdate,m.user_generated AS userGenerated,m.widget_key,m.param");
        $objParameter->appendFrom("WIDGET m,WIDGET_CATEGORY mc,WIDGET_CATEGORY_MAPPING mcm");
        $objParameter->andWhereEqual("m.widget_id=mcm.widget_id");
        $objParameter->andWhereEqual("mc.category_id=mcm.category_id");
        // 1=widget, 2=widget template
        $arrWidgetTypeInAddWidgets = array_keys($this->objFramework->getWidgetPoolFactory()->getWidgetPoolOpt()->getWidgetTypeInAddWidgets());
        $objParameter->andWhereIn("m.widget_type", $arrWidgetTypeInAddWidgets);
        $objParameter->andWhereEqual("widget_status", '1');
        $objParameter->setOrderBy("m.edittime DESC,m.widget_id ASC");
        // ArrsData Before Group Category
        $arrsDataTmp = $this->objDataObject->querySelectAllByParameter($objParameter);
        
        // Step1 : start to merge format to $arrsDataByWidgetName
        // merge format example as below:
        // $arrsDataByWidgetName['modFlickr'] = array('widget_id'=>'1','category'=>'WidgetFramework,IDF'...);
        // $arrsDataByWidgetName['modSearch'] = array('widget_id'=>'2','category'=>'WidgetFramework'...);
        $arrsDataByWidgetName = array();
        if(is_array($arrsDataTmp) && $arrsDataTmp){
            foreach($arrsDataTmp as $arrDataTmp){
                $widget_name = $arrDataTmp['name'];
                if(isset($arrsDataByWidgetName[$widget_name])){ //If widget_name is under multiple Category
                    $strCategory = $arrsDataByWidgetName[$widget_name]['category'];
                    $arrCategory = explode(',', $strCategory);
                    if(! in_array($arrDataTmp['category'], $arrCategory)){
                        $arrCategory[] = $arrDataTmp['category'];
                        $arrsDataByWidgetName[$widget_name]['category'] = implode(',', $arrCategory); // join Category to CategoryA,CategoryB
                    }
                }else{
                    $arrsDataByWidgetName[$widget_name] = $arrDataTmp;
                }
            }
        }
        // transform $arrsDataByWidgetName to $arrsData
        // $arrsDataByWidgetName['modFlickr'] = array('widget_id'=>'1','category'=>'WidgetFramework,IDF'...);
        // $arrsDataByWidgetName['modSearch'] = array('widget_id'=>'2','category'=>'WidgetFramework'...);
        // to 
        // $arrsDataByWidgetName[] = array('widget_id'=>'1','category'=>'WidgetFramework,IDF'...);
        // $arrsDataByWidgetName[] = array('widget_id'=>'2','category'=>'WidgetFramework'...);
        $arrsData = array();
        if(is_array($arrsDataByWidgetName) && $arrsDataByWidgetName){
            foreach($arrsDataByWidgetName as $arrDataByWidgetName){
                $arrsData[] = $arrDataByWidgetName;
            }
        }
        return $arrsData;
    }
    /**
     *\brief Description
     * - This is main() method that excute all the filter policy which existed in Table WP_UPDATE_FILTER
     */
    public function execDbUpdateFilter(){
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        $objParameter->appendFrom('WP_UPDATE_FILTER');
        $arrsData = $this->objDataObject->querySelectAllByParameter($objParameter);
        if(! (is_array($arrsData) && $arrsData)){
            return true;
        }
        $isSuccess = true;
        foreach($arrsData as $arrData){
            $strCategory = $arrData['filter_target'];
            $numberVersion = $arrData['filter_condition'];
            switch($arrData['file_interface']){
                case 'turnOnWidgetOfCategoryByVersion.php':
                    $isSuccess = $isSuccess && $this->turnOnWidgetOfCategoryByVersion($strCategory, $numberVersion);
                    break;
                case 'turnOffWidgetOfCategoryByVersion.php':
                    $isSuccess = $isSuccess && $this->turnOffWidgetOfCategoryByVersion($strCategory, $numberVersion);
                    break;
            }
        }
        return $isSuccess;
    }
    /************************************************
     * WIDGET_COMPONENT,WIDGET_COMPONENT_CATEGORY,WIDGET_COMPONENT_CATEGORY_MAPPING Relative API @START
     ***********************************************/
    /**
     *\brief Description
     * - This is the main() method that synchronize All [comX]/component.xml to DataBase
     * - [comX] represent all widgetComponent folder in /path/to/widgetPool/wpCurrent/widgetComponent
     */
    public function synWidgetComponentDataAllToDB(){
        $arrDir = glob($this->objWidgetPoolManager->getWPHome() . '/widgetComponent/*', GLOB_ONLYDIR);
        if((is_array($arrDir) && $arrDir)){
            foreach($arrDir as $strFullPathDir){
                // get comA from /path/to/widgetComponent/comA
                $strWidgetComponentName = basename($strFullPathDir);
                $this->synWidgetComponentDataToDBByWidgetComponentName($strWidgetComponentName);
            }
        }
    }
    /**
     *\brief Description
     * - This method will synchronize $strWidgetComponentName/component.xml to DB
     * - $strWidgetComponentName is represent a specific widgetComponent folder
     * @param string $strWidgetComponentName widgetComponent folder name 
     */
    public function synWidgetComponentDataToDBByWidgetComponentName($strWidgetComponentName){
        // get arrDataWidgetComponent from component.xml
        $arrDataWidgetComponent = $this->objWidgetPoolManager->getArrDataWidgetComponentByWidgetComponentName($strWidgetComponentName);
        // 1)If widgetComponent is compatible with OSCE <== @todo
        // syn component.xml to db
        ////if((false === $this->isBaseWidget($arrDataWidget)) && (true === $this->isWidgetCompatibleWithWf($arrDataWidget))){
        $wcomponent_id = $this->insertOrUpdateWidgetComponentByArrData($arrDataWidgetComponent);
        $arrsDataWidgetComponentCategory = $this->objWidgetPoolManager->getArrsDataWidgetComponentCategoryByWidgetComponentName($strWidgetComponentName);
        $this->insertOrUpdateWidgetComponentCategoryAndMappingByArrsData($wcomponent_id, $arrsDataWidgetComponentCategory);
         ////}
    }
    /**
     *\brief Description
     * - This method will delete widgetComponent from DB
     * - $strWidgetName is represent a specific widgetComponent folder
     * @param string $strWidgetComponentName widgetComponent folder name 
     */
    public function deleteWidgetComponentDataFromDBByWidgetComponentName($strWidgetComponentName){
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        $objParameter->appendFrom('WIDGET_COMPONENT');
        $objParameter->appendSelect('wcomponent_id');
        $objParameter->andWhereEqual('wcomponent_name', $strWidgetComponentName);
        $wcomponent_id = $this->objDataObject->querySelectOneByParameter($objParameter);
        if(false === $wcomponent_id){
            $message = __CLASS__ . '::' . __FUNCTION__ . '()=>SELECT wcomponent_id FROM WIDGET_COMPONENT failed! Err Msg:' . $this->objDataObject->getErrMessage();
            throw new WFDbDatabaseObjectException($message);
        }elseif(! $wcomponent_id){
            $message = __CLASS__ . '::' . __FUNCTION__ . '()=>Can\'t find ' . $strWidgetComponentName . ' FROM WIDGET_COMPONENT!';
            throw new WFWidgetPoolWidgetPoolDBException($message);
        }
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        $objParameter->appendFrom('WIDGET_COMPONENT');
        $objParameter->andWhereEqual('wcomponent_id', $wcomponent_id);
        $isSuccess = $this->objDataObject->queryDeleteByParameter($objParameter);
        if(false === $isSuccess){
            $message = __CLASS__ . '::' . __FUNCTION__ . '()=>DELETE FROM WIDGET_COMPONENT WHERE wcomponent_name=' . $strWidgetComponentName . ' failed! Err Msg:' . $this->objDataObject->getErrMessage();
            throw new WFDbDatabaseObjectException($message);
        }
        // Delete Table WIDGET_COMPONENT_CATEGORY_MAPPING
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        $objParameter->appendFrom('WIDGET_COMPONENT_CATEGORY_MAPPING');
        $objParameter->andWhereEqual('wcomponent_id', $wcomponent_id);
        $isSuccess2 = $this->objDataObject->queryDeleteByParameter($objParameter);
        if(false === $isSuccess2){
            $message = __CLASS__ . '::' . __FUNCTION__ . '()=>DELETE FROM WIDGET_COMPONENT_CATEGORY_MAPPING WHERE wcomponent_name=' . $strWidgetComponentName . ' failed! Err Msg:' . $this->objDataObject->getErrMessage();
            throw new WFDbDatabaseObjectException($message);
        }
        return $isSuccess && $isSuccess2;
    }
    /**
     *\brief Description
     * - check is widgetComponent version is compatible with widget framework version
     * @param array $arrDataWidgetComponent
     * @return boolean isWidgetCompatibleWithWf
     */
    /*public function isWidgetComponentCompatibleWithWf($arrDataWidgetComponent){
        $ret = false;
        if(isset($arrDataWidgetComponent['wcomponent_min_support_version'])){
            $version_wf = $this->objConfig->getVersion();
            $wcomponent_min_support_version = $arrDataWidgetComponent['wcomponent_min_support_version'];
            $isVersionNumberValid = $this->objFramework->getTypeFactory()->getString()->isVersionNumberValid($wcomponent_min_support_version);
            if(true === $isVersionNumberValid){
                $wcomponent_min_support_version_float = $this->objFramework->getTypeFactory()->getString()->getVersionFloatByString($wcomponent_min_support_version);
                $version_wf_float = $this->objFramework->getTypeFactory()->getString()->getVersionFloatByString($version_wf);
                $ret = ($version_wf_float >= $wcomponent_min_support_version_float) ? true : false;
            }
        }
        return $ret;
    }*/
    /**
     *\brief Description
     * - This method will synchronize $strPathWidgetComponent/component.xml to DB
     * - $strPathWidgetComponent is the PATH of widgetComponent folder
     * - EX : $strPathWidgetComponent
     * - /Users/jersus/htdocs/CruiseControl/projects/Widget_Framework/TMShare/AJAX-Widget/Dev/AJAX-Widgets-1.7/AJAX-Widgets/src/repository/widgetPool/wpLogId/comFlickr
     * @param string $strWidgetComponentName widgetComponent folder name 
     */
    public function synWidgetComponentDataToDBByWidgetComponentPath($strPathWidgetComponent){
        $arrDataWidgetComponent = $this->objWidgetPoolManager->getArrDataWidgetComponentByWidgetComponentPath($strPathWidgetComponent);
        $arrsDataWidgetComponentCategory = $this->objWidgetPoolManager->getArrsDataWidgetComponentCategoryByWidgetComponentPath($strPathWidgetComponent);
        $wcomponent_id = $this->insertOrUpdateWidgetComponentByArrData($arrDataWidgetComponent);
        $this->insertOrUpdateWidgetComponentCategoryAndMappingByArrsData($wcomponent_id, $arrsDataWidgetComponentCategory);
    }
    /**
     *\brief Description
     * - If WidgetComponent existed, update by $arrDataWidgetComponent.
     * - If WidgetComponent not existed, insert by $arrDataWidgetComponent.
     *\par Variable
     * - EX: $arrDataWidgetComponent
     * array (
     * 'wcomponent_name' => 'comFlickr',
     * 'wcomponent_version' => '1.0',
     * 'wcomponent_status' => '1',
     * 'wcomponent_min_support_version' => '2.0',
     * 'wcomponent_param' => '',
     * 'edittime' => '2011-08-23 16:00:00'
     * )
     * @param array $arrDataWidgetComponent
     * @return integer wcomponent_id
     */
    protected function insertOrUpdateWidgetComponentByArrData($arrDataWidgetComponent){
        //print_r($arrDataWidgetComponent);
        $strWidgetComponentName = isset($arrDataWidgetComponent['wcomponent_name']) && $arrDataWidgetComponent['wcomponent_name'] ? $arrDataWidgetComponent['wcomponent_name'] : '';
        if(! $strWidgetComponentName){
            $message = __CLASS__ . "::" . __FUNCTION__ . "()=>\$arrDataWidgetComponent['wcomponent_name'] is required!";
            throw new WFWidgetPoolWidgetPoolDBException($message);
        }
        $strWidgetComponentVersion = isset($arrDataWidgetComponent['wcomponent_version']) && $arrDataWidgetComponent['wcomponent_version'] ? $arrDataWidgetComponent['wcomponent_version'] : '';
        if(! $strWidgetComponentVersion){
            $message = __CLASS__ . "::" . __FUNCTION__ . "()=>\$arrDataWidgetComponent['wcomponent_version'] is required!";
            throw new WFWidgetPoolWidgetPoolDBException($message);
        }
        $arrDataWidgetComponent['wcomponent_status'] = isset($arrDataWidgetComponent['wcomponent_status']) ? $arrDataWidgetComponent['wcomponent_status'] : '0';
        $isWidgetComponentExisted = $this->isWidgetComponentExistedByWidgetComponentName($strWidgetComponentName);
        if(false === $isWidgetComponentExisted){ //Insert
            $wcomponent_id = $this->insertWidgetComponentByArrData($arrDataWidgetComponent);
        }else{ //Update
            $wcomponent_id = $isWidgetComponentExisted;
            $this->updateWidgetComponentByArrData($wcomponent_id, $arrDataWidgetComponent);
        }
        return $wcomponent_id;
    }
    /**
     *\brief Description
     * - Update WidgetComponent Data by $arrDataWidgetComponent.
     *\par Variable
     * - EX: $arrDataWidgetComponent
     * array (
     * 'wcomponent_name' => 'comFlickr',
     * 'wcomponent_version' => '1.0',
     * 'wcomponent_status' => '1',
     * 'wcomponent_min_support_version' => '2.0',
     * 'wcomponent_param' => '',
     * 'edittime' => '2011-08-23 16:00:00'
     * )
     * @param integer $wcomponent_id
     * @param array $arrDataWidgetComponent
     */
    protected function updateWidgetComponentByArrData($wcomponent_id, $arrDataWidgetComponent){
        $arrDataWidgetComponent = $this->getArrDataWidgetComponentValidByArrData($arrDataWidgetComponent);
        if(is_array($arrDataWidgetComponent) && $arrDataWidgetComponent){
            $objParameter = $this->objWidgetPoolFactory->getParameter();
            $objParameter->appendFrom('WIDGET_COMPONENT');
            $wcomponent_status_update = $this->getWidgetStatusUpdateByWidgetId($wcomponent_id, $arrDataWidgetComponent['wcomponent_version']);
            if(false !== $wcomponent_status_update){
                $arrDataWidgetComponent['wcomponent_status_update'] = $wcomponent_status_update; //0=default,1=new,2=version upgrade
            }
            if(isset($arrDataWidgetComponent['wcomponent_id'])){
                unset($arrDataWidgetComponent['wcomponent_id']); //Skip PRIMARY KEY
            }
            if(isset($arrDataWidgetComponent['wcomponent_version'])){
                $arrDataWidgetComponent['wcomponent_version_float'] = $this->objFramework->getTypeFactory()->getString()->getVersionFloatByString($arrDataWidgetComponent['wcomponent_version']);
            }
            if(isset($arrDataWidgetComponent['wcomponent_min_support_version'])){
                $arrDataWidgetComponent['wcomponent_min_support_version_float'] = $this->objFramework->getTypeFactory()->getString()->getVersionFloatByString($arrDataWidgetComponent['wcomponent_min_support_version']);
            }
            // update edittime of widgetComponent
            if(isset($arrDataWidgetComponent['wcomponent_version']) && $arrDataWidgetComponent['wcomponent_version']){
                $objParameter = $this->objWidgetPoolFactory->getParameter();
                $objParameter->appendSelect('wcomponent_version_float');
                $objParameter->appendFrom('WIDGET_COMPONENT');
                $objParameter->andWhereEqual("wcomponent_id", $wcomponent_id);
                $floatWidgetComponentVersionFloat = $this->objDataObject->querySelectOneByParameter($objParameter);
                // if wcomponent_version in component.xml is newer than db wcomponent_version
                if($floatWidgetComponentVersionFloat < $arrDataWidgetComponent['wcomponent_version']){
                    $arrDataWidgetComponent['edittime'] = time();
                }
            }
            if(array_key_exists('edittime', $arrDataWidgetComponent) && ! $arrDataWidgetComponent['edittime']){ //if edittime is empty, unset to avoid edittime=''
                unset($arrDataWidgetComponent['edittime']);
            }
            $objParameter->setAssocData($arrDataWidgetComponent);
            $objParameter->andWhereEqual("wcomponent_id", $wcomponent_id);
            $isSuccess = $this->objDataObject->queryUpdateByParameter($objParameter);
            if(false === $isSuccess){
                $message = __CLASS__ . '::' . __FUNCTION__ . '()=>UPDATE WIDGET_COMPONENT failed! Err Msg:' . $this->objDataObject->getErrMessage();
                throw new WFDbDatabaseObjectException($message);
            }
            return $isSuccess;
        }
    }
    /**
     *\brief Description
     * - if widgetComponent is to be upgrade, wcomponent_status_update=2;
     * - if widgetComponent is new from WidgetPool Update, wcomponent_status_update=1;
     * - else if widgetComponent is default, wcomponent_status_update=0
     * @param $wcomponent_id
     * @param $strWidgetComponentVersionHasToUpdate
     * @return mix return 2 if widgetComponent is upgrade, return 1 if widgetComponent is new create
     */
    protected function getWidgetComponentStatusUpdateByWcomponentId($wcomponent_id, $strWidgetComponentVersionHasToUpdate){
        $ret = false;
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        $objParameter->appendSelect('wcomponent_version');
        $objParameter->appendFrom('WIDGET_COMPONENT');
        $objParameter->andWhereEqual("wcomponent_id", $wcomponent_id);
        $wcomponent_version = $this->objDataObject->querySelectOneByParameter($objParameter);
        if($wcomponent_version){
            if($wcomponent_version < $strWidgetComponentVersionHasToUpdate){
                $ret = '2'; //0=default,1=new,2=version upgrade
            }else{
                $ret = '0';
            }
        }else{
            $ret = '1'; //0=default,1=new,2=version upgrade
        }
        return $ret;
    }
    /**
     *\brief Description
     * - Insert WidgetComponent Data by $arrDataWidgetComponent.
     *\par Variable
     * - EX: $arrDataWidgetComponent
     * array (
     * 'wcomponent_name' => 'comFlickr',
     * 'wcomponent_version' => '1.0',
     * 'wcomponent_status' => '1',
     * 'wcomponent_min_support_version' => '2.0',
     * 'wcomponent_param' => '',
     * 'edittime' => '2011-08-23 16:00:00'
     * )
     * @param $arrDataWidgetComponent
     * @return mix return lastInsertId of wcomponent_id if insert success, return false if insert fail.
     */
    protected function insertWidgetComponentByArrData($arrDataWidgetComponent){
        $ret = false;
        $arrDataWidgetComponent = $this->getArrDataWidgetComponentValidByArrData($arrDataWidgetComponent);
        if(is_array($arrDataWidgetComponent) && $arrDataWidgetComponent){
            $objParameter = $this->objWidgetPoolFactory->getParameter();
            $objParameter->appendFrom('WIDGET_COMPONENT');
            $strCurrentData = time();
            $arrDataWidgetComponent['createtime'] = $strCurrentData;
            //if component.xml have defined <edittime>2010-11-01 00:00:00</edittime>
            //use 2010-11-01 00:00:00 as edittime
            //else use current server time as edittime
            $arrDataWidgetComponent['edittime'] = (isset($arrDataWidgetComponent['edittime']) && $arrDataWidgetComponent['edittime']) ? strtotime($arrDataWidgetComponent['edittime']) : $strCurrentData;
            $arrDataWidgetComponent['wcomponent_status_update'] = '1'; //1=new,2=version upgrade
            $arrDataWidgetComponent['wcomponent_version_float'] = $this->objFramework->getTypeFactory()->getString()->getVersionFloatByString($arrDataWidgetComponent['wcomponent_version']);
            $arrDataWidgetComponent['wcomponent_min_support_version_float'] = $this->objFramework->getTypeFactory()->getString()->getVersionFloatByString($arrDataWidgetComponent['wcomponent_min_support_version']);
            $objParameter->setAssocData($arrDataWidgetComponent);
            $this->objDataObject->queryInsertByParameter($objParameter);
            $ret = $this->objDataObject->lastInsertId();
        }
        if(false === $ret){
            $message = __CLASS__ . '::' . __FUNCTION__ . '()=>INSERT WIDGET_COMPONENT failed! Err Msg:' . $this->objDataObject->getErrMessage();
            throw new WFDbDatabaseObjectException($message);
        }
        return $ret;
    }
    /**
     *\brief Description
     * - Insert or Update WidgetComponentCategory Data by $arrsDataWidgetComponentCategory.
     *\par Variable
     * - EX $arrDataWidgetComponent :
     * Array
     * (
     * [0] => Array
     * (
     * [category_name] => OSCE client
     * [min_support_version] => 10.5
     * )
     * [1] => Array
     * (
     * [category_name] => OSCE server
     * [min_support_version] => 10.5
     * )
     * ) 
     * @param integer $wcomponent_id
     * @param array $arrsDataWidgetComponentCategory
     */
    protected function insertOrUpdateWidgetComponentCategoryAndMappingByArrsData($wcomponent_id, $arrsDataWidgetComponentCategory){
        if(! (is_array($arrsDataWidgetComponentCategory) && $arrsDataWidgetComponentCategory)){
            return false;
        }
        //Step 1: update Table WIDGET_COMPONENT_CATEGORY
        $arrsWidgetComponentCategoryCurrentInsertOrUpdate = array(); //For syn WIDGET_COMPONENT_CATEGORY_MAPPING
        foreach($arrsDataWidgetComponentCategory as $arrDataWidgetComponentCategory){
            $strWidgetComponentCategoryName = $arrDataWidgetComponentCategory['category_name'];
            //var_dump($strWidgetComponentCategoryName);
            if(! $strWidgetComponentCategoryName){
                throw new WFWidgetPoolWidgetPoolDBException("category_name is required!");
            }
            $floatCategoryProductId = $arrDataWidgetComponentCategory['category_product_id'];
            $isWidgetComponentCategoryExisted = $this->isWidgetComponentCategoryExistedByCategoryName($strWidgetComponentCategoryName, $floatCategoryProductId);
            if(false === $isWidgetComponentCategoryExisted){ //Insert
                $category_id = $this->insertWidgetComponentCategoryByArrData($arrDataWidgetComponentCategory);
            }else{ //Update
                $category_id = $isWidgetComponentCategoryExisted;
                $this->updateWidgetComponentCategoryByArrData($category_id, $arrDataWidgetComponentCategory);
            }
            $arrsWidgetComponentCategoryCurrentInsertOrUpdate[$category_id] = $arrDataWidgetComponentCategory;
        }
        //Step 2: update Table WIDGET_COMPONENT_CATEGORY_MAPPING
        $this->updateWidgetComponentCategoryMappingByWcomponentId($wcomponent_id, $arrsWidgetComponentCategoryCurrentInsertOrUpdate);
         //return $arrsWidgetComponentCategoryCurrentInsertOrUpdate;
    }
    /**
     *\brief Description
     * - Update WidgetComponentCategory Data by $arrsWidgetComponentCategoryCurrentInsertOrUpdate.
     *\par Variable
     * - EX : $arrDataWidgetComponent :
     * Array
     * (
     * [0] => Array
     * (
     * [category_name] => OSCE client
     * [min_support_version] => 10.5
     * )
     * [1] => Array
     * (
     * [category_name] => OSCE server
     * [min_support_version] => 10.5
     * )
     * ) 
     * @param integer $wcomponent_id
     * @param array $arrsWidgetComponentCategoryCurrentInsertOrUpdate This array is used to calculate deletion of TableWidgetComponentCategoryMapping record, 
     * reserve and update category in $arrsWidgetComponentCategoryCurrentInsertOrUpdate, 
     * delete category not in $arrsWidgetComponentCategoryCurrentInsertOrUpdate  .
     */
    protected function updateWidgetComponentCategoryMappingByWcomponentId($wcomponent_id, $arrsWidgetComponentCategoryCurrentInsertOrUpdate){
        //Step1: retrieve all category_id that in db, may be need to delete
        $arrWidgetComponentCategoryIdHasToDelete = $this->getArrWidgetComponentCategoryIdByWcomponentId($wcomponent_id);
        if(is_array($arrsWidgetComponentCategoryCurrentInsertOrUpdate) && $arrsWidgetComponentCategoryCurrentInsertOrUpdate){
            $isSuccess = true;
            foreach($arrsWidgetComponentCategoryCurrentInsertOrUpdate as $category_id => $arrWidgetComponentCategory){
                $arrValue = array();
                $objParameter = $this->objWidgetPoolFactory->getParameter();
                $objParameter->appendFrom('WIDGET_COMPONENT_CATEGORY_MAPPING');
                if(isset($arrWidgetComponentCategoryIdHasToDelete[$category_id])){ //Update if in current db
                    $arrWidgetComponentCategoryMappingValid = $this->getArrDataWidgetComponentCategoryMappingValidByArrData($arrWidgetComponentCategory);
                    if(isset($arrWidgetComponentCategory['min_support_version'])){
                        $arrWidgetComponentCategoryMappingValid['min_support_version'] = $arrWidgetComponentCategory['min_support_version'];
                        $arrWidgetComponentCategoryMappingValid['min_support_version_float'] = $this->objFramework->getTypeFactory()->getString()->getVersionFloatByString($arrWidgetComponentCategoryMappingValid['min_support_version']);
                    }
                    $arrWidgetComponentCategoryMappingValid['edittime'] = time();
                    $objParameter->setAssocData($arrWidgetComponentCategoryMappingValid);
                    $objParameter->andWhereEqual("wcomponent_id", $wcomponent_id);
                    $objParameter->andWhereEqual("category_id", $category_id);
                    $isSuccess2 = $this->objDataObject->queryUpdateByParameter($objParameter);
                    unset($arrWidgetComponentCategoryIdHasToDelete[$category_id]); // This category_id no need to delete
                }else{ //Insert If not in current db
                    $arrWidgetComponentCategoryMappingValid = array();
                    $arrWidgetComponentCategoryMappingValid['wcomponent_id'] = $wcomponent_id;
                    $arrWidgetComponentCategoryMappingValid['category_id'] = $category_id;
                    if(isset($arrWidgetComponentCategory['min_support_version'])){
                        $arrWidgetComponentCategoryMappingValid['min_support_version'] = $arrWidgetComponentCategory['min_support_version'];
                        $arrWidgetComponentCategoryMappingValid['min_support_version_float'] = $this->objFramework->getTypeFactory()->getString()->getVersionFloatByString($arrWidgetComponentCategoryMappingValid['min_support_version']);
                    }
                    $arrWidgetComponentCategoryMappingValid['createtime'] = time();
                    $objParameter->setAssocData($arrWidgetComponentCategoryMappingValid);
                    $isSuccess2 = $this->objDataObject->queryInsertByParameter($objParameter);
                }
                $isSuccess = $isSuccess && $isSuccess2;
            }
            if(false === $isSuccess){
                $message = __CLASS__ . '::' . __FUNCTION__ . '()=>UPDATE/INSERT WIDGET_COMPONENT_CATEGORY_MAPPING failed! Err Msg:' . $this->objDataObject->getErrMessage();
                throw new WFDbDatabaseObjectException($message);
            }
        }
        //Step2: Delete the category_id that have to delete
        if(is_array($arrWidgetComponentCategoryIdHasToDelete) && $arrWidgetComponentCategoryIdHasToDelete){
            $objParameter = $this->objWidgetPoolFactory->getParameter();
            $objParameter->appendFrom('WIDGET_COMPONENT_CATEGORY_MAPPING');
            $objParameter->andWhereEqual("wcomponent_id", $wcomponent_id);
            $objParameter->andWhereIn('category_id', $arrWidgetComponentCategoryIdHasToDelete);
            $isSuccess = $this->objDataObject->queryDeleteByParameter($objParameter);
            if(false === $isSuccess){
                $message = __CLASS__ . '::' . __FUNCTION__ . '()=>DELETE WIDGET_COMPONENT_CATEGORY WHERE wcomponent_id=? failed! Err Msg:' . $this->objDataObject->getErrMessage();
                throw new WFDbDatabaseObjectException($message);
            }
        }
    }
    /**
     *\brief Description
     * - Update WidgetComponentCategory Data by $arrDataWidgetComponentCategory.
     * - EX : $arrDataWidgetComponent :
     * Array
     * (
     * [0] => Array
     * (
     * [category_name] => OSCE client
     * [min_support_version] => 10.5
     * )
     * [1] => Array
     * (
     * [category_name] => OSCE server
     * [min_support_version] => 10.5
     * )
     * ) 
     * @param integer $category_id
     * @param array $arrDataWidgetComponentCategory  
     */
    protected function updateWidgetComponentCategoryByArrData($category_id, $arrDataWidgetComponentCategory){
        $arrDataWidgetComponentCategory = $this->getArrDataWidgetComponentCategoryValidByArrData($arrDataWidgetComponentCategory);
        if(is_array($arrDataWidgetComponentCategory) && $arrDataWidgetComponentCategory){
            $objParameter = $this->objWidgetPoolFactory->getParameter();
            $objParameter->appendFrom('WIDGET_COMPONENT_CATEGORY');
            //Avoid update category_id
            if(isset($arrDataWidgetComponentCategory['category_id'])){
                unset($arrDataWidgetComponentCategory['category_id']); //Skip PRIMARY KEY
            }
            //trim category_name
            if(isset($arrDataWidgetComponentCategory['category_name'])){
                $arrDataWidgetComponentCategory['category_name'] = trim($arrDataWidgetComponentCategory['category_name']);
            }
            //var_dump($arrDataWidgetComponentCategory);
            if(! isset($arrDataWidgetComponentCategory['edittime'])){
                $arrDataWidgetComponentCategory['edittime'] = time();
            }
            $objParameter->setAssocData($arrDataWidgetComponentCategory);
            $objParameter->andWhereEqual('category_id', $category_id);
            $isSuccess = $this->objDataObject->queryUpdateByParameter($objParameter);
            if(false === $isSuccess){
                $message = __CLASS__ . '::' . __FUNCTION__ . '()=>UPDATE WIDGET_COMPONENT_CATEGORY assocData WHERE category_id=? failed! Err Msg:' . $this->objDataObject->getErrMessage();
                throw new WFDbDatabaseObjectException($message);
            }
        }
    }
    /**
     *\brief Description
     * - Insert WidgetComponentCategory Data by $arrDataWidgetComponentCategory.
     * - EX : $arrDataWidgetComponent :
     * Array
     * (
     * [0] => Array
     * (
     * [category_name] => OSCE client
     * [min_support_version] => 10.5
     * )
     * [1] => Array
     * (
     * [category_name] => OSCE server
     * [min_support_version] => 10.5
     * )
     * ) 
     * @param array $arrDataWidgetComponentCategory  
     * @return mix return lastInsertId of category_id if insert success, return false if insert fail.
     */
    protected function insertWidgetComponentCategoryByArrData($arrDataWidgetComponentCategory){
        $ret = false;
        // Verify $arrDataWidgetComponentCategory is integrity
        $arrDataWidgetComponentCategory = $this->getArrDataWidgetComponentCategoryValidByArrData($arrDataWidgetComponentCategory);
        if(is_array($arrDataWidgetComponentCategory) && $arrDataWidgetComponentCategory){
            $objParameter = $this->objWidgetPoolFactory->getParameter();
            $objParameter->appendFrom('WIDGET_COMPONENT_CATEGORY');
            if(isset($arrDataWidgetComponentCategory['category_id'])){
                unset($arrDataWidgetComponentCategory['category_id']); //Skip PRIMARY KEY of TableWidgetComponentCategory
            }
            //trim category_name
            if(isset($arrDataWidgetComponentCategory['category_name'])){
                $arrDataWidgetComponentCategory['category_name'] = trim($arrDataWidgetComponentCategory['category_name']);
            }
            $arrDataWidgetComponentCategory['createtime'] = time();
            $objParameter->setAssocData($arrDataWidgetComponentCategory);
            $this->objDataObject->queryInsertByParameter($objParameter);
            $ret = $this->objDataObject->lastInsertId();
        }
        if(false === $ret){
            $message = "INSERT WIDGET_COMPONENT_CATEGORY failed! Err Msg:" . $this->objDataObject->getErrMessage();
            throw new WFDbDatabaseObjectException($message);
        }
        return $ret;
    }
    /**
     *\brief Description
     * - This method will get $arrWidgetComponentCategoryId from db by $wcomponent_id
     * - EX : $arrWidgetComponentCategoryId :
     * Array (
     * [0] => 1,
     * [1] => 2
     * )
     * @param $wcomponent_id
     * @return array
     */
    protected function getArrWidgetComponentCategoryIdByWcomponentId($wcomponent_id){
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        $objParameter->appendFrom('WIDGET_COMPONENT_CATEGORY_MAPPING');
        $objParameter->andWhereEqual("wcomponent_id", $wcomponent_id);
        $objParameter->appendSelect('category_id');
        $arrsData = $this->objDataObject->querySelectAllByParameter($objParameter);
        if(false === $arrsData){
            $message = __CLASS__ . '::' . __FUNCTION__ . '()=>SELECT category_id FROM WIDGET_COMPONENT WHERE wcomponent_id=? failed! Err Msg:' . $this->objDataObject->getErrMessage();
            throw new WFDbDatabaseObjectException($message);
        }
        $ret = array();
        if(! is_array($arrsData) && $arrsData){
            return $ret;
        }
        foreach($arrsData as $arrData){
            $ret[$arrData['category_id']] = $arrData['category_id'];
        }
        return $ret;
    }
    /**
     *\brief Description
     * - This method will verify the integrity of $arrDataWidgetComponent
     * @param $arrDataWidgetComponent
     * @return array
     */
    protected function getArrDataWidgetComponentValidByArrData($arrDataWidgetComponent){
        $ret = array();
        if(is_array($arrDataWidgetComponent) && $arrDataWidgetComponent){
            $arrTableSchemaColumnValid = $this->objWidgetPoolFactory->getWidgetPoolOpt()->getTableSchemaColumnWidgetComponent();
            foreach($arrDataWidgetComponent as $strColumnName => $mixColumnValue){
                if(true === in_array($strColumnName, $arrTableSchemaColumnValid)){
                    $ret[$strColumnName] = $mixColumnValue;
                }
            }
        }
        return $ret;
    }
    /**
     *\brief Description
     * - This method will verify the integrity of $arrDataWidgetComponentCategory
     * @param $arrDataWidgetComponentCategory
     * @return array
     */
    protected function getArrDataWidgetComponentCategoryValidByArrData($arrDataWidgetComponentCategory){
        $ret = array();
        if(is_array($arrDataWidgetComponentCategory) && $arrDataWidgetComponentCategory){
            $arrTableSchemaColumnValid = $this->objWidgetPoolFactory->getWidgetPoolOpt()->getTableSchemaColumnWidgetComponentCategory();
            foreach($arrDataWidgetComponentCategory as $strColumnName => $mixColumnValue){
                if(true === in_array($strColumnName, $arrTableSchemaColumnValid)){
                    $ret[$strColumnName] = $mixColumnValue;
                }
            }
        }
        return $ret;
    }
    /**
     *\brief Description
     * - This method will verify the integrity of $arrDataWidgetComponentCategory
     * @param $arrDataWidgetComponentCategory
     * @return array
     */
    protected function getArrDataWidgetComponentCategoryMappingValidByArrData($arrDataWidgetComponentCategory){
        $ret = array();
        if(is_array($arrDataWidgetComponentCategory) && $arrDataWidgetComponentCategory){
            $arrTableSchemaColumnValid = $this->objWidgetPoolFactory->getWidgetPoolOpt()->getTableSchemaColumnWidgetComponentCategoryMapping();
            foreach($arrDataWidgetComponentCategory as $strColumnName => $mixColumnValue){
                if(true === in_array($strColumnName, $arrTableSchemaColumnValid)){
                    $ret[$strColumnName] = $mixColumnValue;
                }
            }
        }
        return $ret;
    }
    /**
     *\brief Description
     * - This method will check is the specific widgetComponent is existed in TableWidgetComponent 
     * @param $strWidgetComponentName
     * @return mix return false is not existed in TableWidget, return wcomponent_id is the widgetComponent exist in TableWidgetComponent 
     */
    protected function isWidgetComponentExistedByWidgetComponentName($strWidgetComponentName){
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        $objParameter->appendSelect('wcomponent_id');
        $objParameter->appendFrom("WIDGET_COMPONENT");
        $objParameter->andWhereEqual("wcomponent_name", $strWidgetComponentName);
        $wcomponent_id = $this->objDataObject->querySelectOneByParameter($objParameter);
        if(false === $wcomponent_id){
            $message = __CLASS__ . '::' . __FUNCTION__ . '()=>SELECT wcomponent_id FROM WIDGET_COMPONENT WHERE wcomponent_name=? fetchOne failed! Err Msg:' . $this->objDataObject->getErrMessage();
            throw new WFDbDatabaseObjectException($message);
        }
        return $wcomponent_id ? $wcomponent_id : false;
    }
    /**
     *\brief Description
     * - This method will check is the specific WIDGET_COMPONENT_CATEGORY is existed in TableWidgetComponentCategory 
     * @param $strCategoryName
     * @return mix return false is not existed in TableWidgetComponentCategory, return category_id is the widgetComponent exist in TableWidgetComponentCategory 
     */
    protected function isWidgetComponentCategoryExistedByCategoryName($strCategoryName, $floatCategoryProductId = null){
        $objParameter = $this->objWidgetPoolFactory->getParameter();
        $objParameter->appendSelect('category_id');
        $objParameter->appendFrom('WIDGET_COMPONENT_CATEGORY');
        $objParameter->andWhereEqual("category_name", $strCategoryName);
        if(null !== $floatCategoryProductId){
            $objParameter->andWhereEqual("category_product_id", $floatCategoryProductId);
        }
        $category_id = $this->objDataObject->querySelectOneByParameter($objParameter);
        if(false === $category_id){
            $message = __CLASS__ . '::' . __FUNCTION__ . '()=>SELECT category_id FROM WIDGET_COMPONENT_CATEGORY WHERE category_name=? fetchOne failed! Err Msg:' . $this->objDataObject->getErrMessage();
            throw new WFDbDatabaseObjectException($message);
        }
        return $category_id ? $category_id : false;
    }
/************************************************
 * WIDGET_COMPONENT,WIDGET_COMPONENT_CATEGORY,WIDGET_COMPONENT_CATEGORY_MAPPING Relative API @END
 ***********************************************/
}
